package com.example.njupt.base.fragment;

import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.LayoutRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.UiThread;
import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleEventObserver;

import com.example.njupt.R;
import com.example.njupt.base.BaseActivity;
import com.example.njupt.base.mvp.BasePresenter;
import com.example.njupt.base.mvp.IView;
import com.example.njupt.views.toolbar.ToolbarHelper;
import com.trello.rxlifecycle2.components.support.RxFragment;

import org.greenrobot.eventbus.EventBus;

import java.util.List;

import butterknife.ButterKnife;
import butterknife.Unbinder;

/**
 * Author:      mwang
 * Create Date: Created in 2021/5/25 14:44
 * Update Date:
 * Modified By:
 * Description:
 */
public abstract class BaseFragment<P extends BasePresenter> extends RxFragment implements IView {

    protected P mPresenter;

    private Unbinder unbinder;
    private BaseActivity activity;
    private ToolbarHelper toolbarHelper;
    public View view;
    public Context context;

    /**
     * 懒加载过
     */
    private boolean isLazyLoaded;
    /**
     * Fragment的View加载完毕的标记
     */
    private boolean isPrepared;

    private OnFragmentVisibilityChangedListener mFragmentVisibilityChangedListener;

    private void provideToolbar() {
        if (null == toolbarHelper && null != getView()) {
            Toolbar toolbar = getView().findViewById(R.id.toolbar);
            if (null == toolbar) {
                throw new IllegalArgumentException("toolbar must included in layout file");
            }
            toolbarHelper = new ToolbarHelper(activity, toolbar);
            toolbarHelper.setImmersive(false);
        }
    }

    public ToolbarHelper getToolbarHelper() {
        provideToolbar();
        return toolbarHelper;
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        if (view == null) {
            view = inflater.inflate(getLayoutId(), null);
            unbinder = ButterKnife.bind(this, view);
            if (useEventBus()) {
                EventBus.getDefault().register(this);//注册eventBus
            }
        }

        ButterKnife.bind(this, view);
        context = getActivity();

        ViewGroup parent = (ViewGroup) view.getParent();
        if (parent != null) {
            parent.removeView(view);
        }
        return view;
    }

    private boolean currentVisible = false;
    private Lifecycle.Event mCurrentLifeCycleEvent;

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        mPresenter = createPresenter();
        if (mPresenter != null) {
            mPresenter.attachView(this);
        }

        getLifecycle().addObserver((LifecycleEventObserver) (source, event) -> {
            mCurrentLifeCycleEvent = event;
            checkCurrentVisible(false);
        });

        Fragment parentFragment = BaseFragment.this.getParentFragment();
        if (parentFragment instanceof BaseFragment) {
            ((BaseFragment) parentFragment).setOnFragmentVisibilityChangedListener(visible -> {
                if (visible && !currentVisible && isVisible() && parentFragment.isVisible() && mCurrentLifeCycleEvent == Lifecycle.Event.ON_RESUME) {
                    currentVisible = true;
                    if (null != mFragmentVisibilityChangedListener) {
                        mFragmentVisibilityChangedListener.onFragmentVisibilityChanged(true);
                    }
                }
            });
        }

        initView();
        initListener();
    }

    private void checkCurrentVisible(boolean transitionChange) {
        if (currentVisible) {
            if (transitionChange && !isVisible()) {
                currentVisible = false;
                hideChildren();
            }
            if (!transitionChange && (mCurrentLifeCycleEvent == Lifecycle.Event.ON_PAUSE || mCurrentLifeCycleEvent == Lifecycle.Event.ON_STOP)) {
                currentVisible = false;
                hideChildren();
            }
        } else {
            if (transitionChange && isVisible()) {
                currentVisible = true;
                if (null != mFragmentVisibilityChangedListener) {
                    mFragmentVisibilityChangedListener.onFragmentVisibilityChanged(true);
                }
            }
            if (!transitionChange && mCurrentLifeCycleEvent == Lifecycle.Event.ON_RESUME && isVisible()
                    && (getParentFragment() == null || getParentFragment().isVisible())
                    && (getParentFragment() == null || getParentFragment().getParentFragment() == null || getParentFragment().getParentFragment().isVisible())
            ) {
                currentVisible = true;
                if (null != mFragmentVisibilityChangedListener) {
                    mFragmentVisibilityChangedListener.onFragmentVisibilityChanged(true);
                }
            }
        }
    }

    private void hideChildren() {
        List<Fragment> fragments = this.getChildFragmentManager().getFragments();
        for (Fragment childFragment : fragments) {
            if (childFragment instanceof BaseFragment) {
                ((BaseFragment) childFragment).onFragmentVisibilityChanged(false);
            }
        }
    }

    public void onFragmentVisibilityChanged(boolean visible) {
        if (visible != currentVisible) {
            currentVisible = visible;
        }
    }

    public static int getStatusBarHeight(Context context) {
        int result = 0;
        int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
        if (resourceId > 0) {
            result = context.getResources().getDimensionPixelSize(resourceId);
        }

        return result;
    }

    /**
     * 含有Bundle通过Class跳转界面
     **/
    public void startActivityForResult(Class<?> cls, Bundle bundle, int requestCode) {
        Intent intent = new Intent();
        intent.setClass(getBaseActivity(), cls);
        if (bundle != null) {
            intent.putExtras(bundle);
        }
        startActivityForResult(intent, requestCode);
    }

    /**
     * 含有Bundle通过Class跳转界面
     **/
    public void startActivity(Class<?> cls, Bundle bundle) {
        Intent intent = new Intent();
        intent.setClass(getBaseActivity(), cls);
        if (bundle != null) {
            intent.putExtras(bundle);
        }
        startActivity(intent);
    }

    public interface OnFragmentVisibilityChangedListener {
        void onFragmentVisibilityChanged(boolean visible);
    }

    public void setOnFragmentVisibilityChangedListener(OnFragmentVisibilityChangedListener mFragmentVisibilityChangedListener) {
        this.mFragmentVisibilityChangedListener = mFragmentVisibilityChangedListener;
    }

    public BaseActivity getBaseActivity() {
        return activity;
    }

    @Override
    public void showLoading() {
        activity.showLoadingDialog();
    }

    @Override
    public void hideLoading() {
        activity.hideLoadingDialog();
    }

    @Override
    public void onHiddenChanged(boolean hidden) {
        super.onHiddenChanged(hidden);
        checkCurrentVisible(true);
    }

    @Override
    public void onAttach(@NonNull Context context) {
        super.onAttach(context);
        if (context instanceof BaseActivity) {
            this.activity = (BaseActivity) this.getActivity();
        }
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        initData();
        isPrepared = true;
        lazyLoad();
    }

    /**
     * 第二步
     * 此方法会在onCreateView(）之前执行
     * 当viewPager中fragment改变可见状态时也会调用
     * 当fragment 从可见到不见，或者从不可见切换到可见，都会调用此方法
     */
    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
        lazyLoad();
    }

    private void lazyLoad() {
        if (getUserVisibleHint() && isPrepared && !isLazyLoaded) {
            onLazyLoad();
            isLazyLoaded = true;
        }
    }

    /**
     * 第四步:定义抽象方法onLazyLoad(),具体加载数据的工作,交给子类去完成
     */
    @UiThread
    public abstract void onLazyLoad();

    @Override
    public void onDestroyView() {
        super.onDestroyView();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (mPresenter != null) {
            mPresenter.detachView();
        }
        if (unbinder != null) {
            unbinder.unbind();
        }
        if (useEventBus()) {
            if (EventBus.getDefault().isRegistered(this)) {
                EventBus.getDefault().unregister(this);//注销eventBus
            }
        }

    }

    protected abstract @LayoutRes
    int getLayoutId();

    protected abstract void initView();

    protected abstract void initListener();

    protected abstract void initData();

    protected abstract P createPresenter();

    protected boolean useEventBus() {
        return false;
    }
}
